﻿using System;
using System.Html;
using jQueryApi;

namespace Quicklight.Web.Razor {

   /// <summary>
   /// This class binds to an inner content of an element. This class simply locates the element identified by the element locator and calls an abstract method Bind
   /// to do the actual binding. Extend this class to bind something to the inner content
   /// </summary>
   public abstract class ContentBinder : Binder {

      /// <summary>
      /// Constructs an ContentBinder
      /// </summary>
      public ContentBinder() {
      }

      /// <summary>
      /// Creates and returns an element locator. The element locator is a bind element with the specified key as id
      /// </summary>
      /// <param name="key">Unique key for this binder instance</param>
      /// <returns>The element locator that will be used by the Bind method to locate the element</returns>
      public override string GetElementLocator(string key) {
         return String.Format(@"<bind id=""{0}"" />", key);
      }

      /// <summary>
      /// This method locates the element using the element locator, ensures that it has an id, then calls the abstract Bind method to bind the element
      /// </summary>
      /// <param name="key">Unique key for this binder instance</param>
      public override void Bind(string key) {
         string elementLocator = key.Replace("(", @"\(").Replace(":", @"\:").Replace("|", @"\|").Replace(@"\", @"\\").Replace(".", @"\.").Replace(")", @"\)");
         jQueryObject jQueryObject = jQuery.Select(String.Format(@"bind[id=""{0}""]", elementLocator));
         if (jQueryObject == null)
            return;

         string id = jQueryObject.Parent().GetAttribute("id");
         if (String.IsNullOrEmpty(id)) {
            id = key;
            jQueryObject.Parent().Attribute("id", id);
         }

         Element element = Document.Instance.GetElementById(id);
         Bind(element);
      }

      /// <summary>
      /// Abstract Bind method that does the actual binding
      /// </summary>
      /// <param name="element">Element to bind to</param>
      protected abstract void Bind(Element element);

   }
}
